package com.cib.icarus.desensitize.wrapper;

import com.cib.icarus.core.utils.ClassUtils;
import com.cib.icarus.core.utils.DesensitizeInfoUtils;
import com.cib.icarus.core.utils.internals.StrUtils;
import com.cib.icarus.desensitize.annotation.BitDesensitize;
import com.cib.icarus.desensitize.annotation.PatternDesensitize;
import com.cib.icarus.desensitize.annotation.StrategyDesensitize;
import com.cib.icarus.desensitize.annotation.DesAbstractStrategy;
import org.reflections.ReflectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Objects;
import java.util.Set;

public class DesensitizeHelper {

    public static <T> T getAnnotation(Field field, Class<T> annotationClass) {
        // FIXME need to replace this function with ReflectionUtils
        Set<Annotation> annotations = ReflectionUtils.getAllAnnotations(field);
        for (Annotation annotation : annotations) {
            if (Objects.equals(annotation.annotationType(), annotationClass)) {
                return (T) annotation;
            }
        }
        return null;
    }


    public static boolean notDesensitizationClassType(Object object) {
        return null == object
                || ClassUtils.isPrimitiveType(object.getClass())
                || ClassUtils.isPackageType(object.getClass());
    }

    public static boolean notDesensitizationFieldType(Field field) {
        return null == field
                || Class.class.isAssignableFrom(field.getType())
                || ClassUtils.isPrimitiveType(field.getType())
                || ClassUtils.isPackageType(field.getType());
    }


    /**
     * @param source 源数据
     * @return 源数据是否可以被处理(脱敏)
     */
    public static boolean canDesensitization(String source) {
        return !StrUtils.isBlank(source) && !"null".equals(source);
    }

    public static String desensitization(final String source, StrategyDesensitize strategyDesensitize)
            throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        DesAbstractStrategy desAbstractStrategy = strategyDesensitize.strategy().getDeclaredConstructor().newInstance();
        char placeholder = strategyDesensitize.placeholder();
        return desAbstractStrategy.desensitization(source, placeholder);
    }


    public static String desensitizationByBit(final String source, BitDesensitize bitDesensitize) {
        char placeholder = bitDesensitize.placeholder();
        int begin = bitDesensitize.startBit();
        int end = bitDesensitize.endBit();
        return desensitizationByBit(source, placeholder, begin, end);
    }

    public static String desensitizationByPattern(String source, PatternDesensitize patternDesensitize) {
        String regex = patternDesensitize.regex();
        String replacement = patternDesensitize.replacement();
        return desensitizationByPattern(source, regex, replacement);
    }

    public static String desensitizationByBit(final String source, char placeholder, int begin, int end) {
        if (!canDesensitization(source)) {
            return source;
        }
        return DesensitizeInfoUtils.hide(source, placeholder, begin, end);
    }

    public static String desensitizationByPattern(String source, String regex, String replacement) {
        if (!canDesensitization(source) || StrUtils.isBlank(regex) || StrUtils.isBlank(replacement)) {
            return source;
        }
        return DesensitizeInfoUtils.patternReplace(source, regex, replacement);
    }


}
